﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Mimoza.RdpPlugin
{
    public struct ResolutionMapping
    {
        public ResolutionMapping(Resolution res, int w, int h)
        {
            resolution = res;
            width = w;
            height = h;
        }

        public Resolution resolution;
        public int width;
        public int height;
    }

    public class RdpFile
    {
        List<ResolutionMapping> mapping = new List<ResolutionMapping>();

        public RdpFile()
        {
            AddMapRecord(Resolution.Res640x480, 640, 480);
            AddMapRecord(Resolution.Res800x600, 800, 600);
            AddMapRecord(Resolution.Res1024x768, 1024, 768);
            AddMapRecord(Resolution.Res1280x800, 1280, 800);
            AddMapRecord(Resolution.Res1280x720, 1280, 720);
            AddMapRecord(Resolution.Res1280x768, 1280, 768);
            AddMapRecord(Resolution.ResFullScreen, 800, 600);

            string osName = Common.GlobalSettings.Licence.OSName;
            if (osName.Contains("CE"))
            {
                IsRdpCE = true;
                if (osName.Contains("5.")) IsOldRdpVersion = true;
            }
        }

        public void CreateFile(string fullFileName, RdpData data, Guid policyId)
        {
            string fileText = FillTemplate(data, policyId);

            Directory.CreateDirectory(Path.GetDirectoryName(fullFileName));

            if (IsOldRdpVersion)
            {
                using (FileStream writer = File.Create(fullFileName))
                {
                    byte[] buff = Encoding.Unicode.GetBytes(fileText);
                    writer.WriteByte(0xFF);
                    writer.WriteByte(0xFE);
                    writer.Write(buff, 0, buff.Length);
                }
            }
            else
            {
                using (StreamWriter writer = File.CreateText(fullFileName))
                {
                    writer.Write(fileText);
                    writer.Flush();
                }
            }
        }

        private bool IsOldRdpVersion
        {
            get { return m_bIsOldRdpVersion; }
            set { m_bIsOldRdpVersion = value; }
        }

        private bool IsRdpCE
        {
            get { return m_bIsRdpCE; }
            set { m_bIsRdpCE = value; }
        }

        private string FillTemplate(RdpData data, Guid policyId)
        {
            string text = IsOldRdpVersion ? Resource.Rdp50FileTemplate : Resource.RdpFileTemplate;

            text = text.Replace("%COMP%", data.Computer);

            ResolutionMapping mapping = FindResolutionMapping(data.Resolution);

            text = text.Replace("%WIDTH%", mapping.width.ToString());
            text = text.Replace("%HEIGHT%", mapping.height.ToString());

            int screenMode = IsOldRdpVersion ? 0 : 1; // by res
            if (data.Resolution == Resolution.ResFullScreen)
                screenMode = IsOldRdpVersion ? 1 : 2;    
            text = text.Replace("%SCREENMODE%", screenMode.ToString());

            int displayConnBar = data.IsDisplayConnectionBar?1:0;
            text = text.Replace("%DISPLAYBAR%", displayConnBar.ToString());

            text = text.Replace("%USERNAME%", data.UserName);

            text = text.Replace("%COLORDEPTH%", GetDpp(data.ColorDepth).ToString());

            text = text.Replace("%DRIVES%",
                (data.UsingDevice.UseDiskDrives ? 1 : 0).ToString());
            text = text.Replace("%PRINTERS%",
                (data.UsingDevice.UsePrinters ? 1 : 0).ToString());
            text = text.Replace("%SERPORTS%",
                (data.UsingDevice.UseSerialPorts ? 1 : 0).ToString());
            text = text.Replace("%SMARTCARDS%",
                (data.UsingDevice.UseSmartCards ? 1 : 0).ToString());

            text = text.Replace("%KEYBOARDHOOK%",
                GetKeyboradHookVal(data.Keyboard).ToString());

            text = text.Replace("%AUDIOMODE%",
                GetSoundDirection(data.Sound).ToString());

            text = text.Replace("%ALTSHELL%", 
                data.StartProgram.IsStartEnabled?data.StartProgram.ProgramPath:"");
            text = text.Replace("%ALTSHELLFOLDER%",
                data.StartProgram.IsStartEnabled ? data.StartProgram.ProgramFolder : "");

            if (data.IsPersistentShortcut)
                text = text.Replace("%POLICYID%", policyId.ToString());

            int val = data.IsStartOnStartup ? 1 : 0;
            text = text.Replace("%STARTUPFLAG%", val.ToString() );

            return text;
        }

        private void AddMapRecord(Resolution res, int w, int h)
        {
            mapping.Add(new ResolutionMapping(res, w, h));
        }

        private ResolutionMapping FindResolutionMapping(Resolution res)
        {
            int index = mapping.FindIndex(r => r.resolution == res);
            if (index<0)
            {
                Common.Logger.Log.Error("RdpFile.CreateFile Error occured: type of resolution (" + 
                    res.ToString() + ") in not defined.");
                throw new ArgumentException();
            }

            return mapping[index];
        }

        private int GetDpp(ColorDepth color)
        {
            int res = 0;
            switch(color)
            {
                case ColorDepth.Color8Bit:
                    res = IsOldRdpVersion? 1 : 8;
                    break;
                case ColorDepth.Color16Bit:
                    res = IsOldRdpVersion ? 3 : 16;
                    break;
                case ColorDepth.Color24Bit:
                    res = IsOldRdpVersion ? 4 : 24;
                    break;
                case ColorDepth.Color32Bit:
                    res = IsOldRdpVersion ? 4 : 32;
                    break;
                default:
                    res = IsOldRdpVersion ? 4 : 16;
                    break;
            }

            return res;
        }

        private int GetKeyboradHookVal(Keyboard keyboard)
        {
            return (int)keyboard;
        }

        private int GetSoundDirection(Sound soundDir)
        {
            switch (soundDir)
            {
                case Sound.BringToComputer:
                    return 0;
                case Sound.LeaveAtRemoteComputer:
                    return 1;
                case Sound.DoNotPlay:
                    return 2;
                default:
                    return 0;
            }
        }

        bool m_bIsOldRdpVersion = false; // Rdp 5
        bool m_bIsRdpCE = false;
    }
}
